home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / system / fstat.zip / FSTAT.C < prev    next >
Text File  |  1989-12-11  |  7KB  |  219 lines

  1. /*
  2.  *  FSTAT -  a utility to list the all open files known to the system
  3.  *  along with miscellaneous information such as length, offset, handle
  4.  *  count, access modes, device information or drive information, and
  5.  *  the program which opened the file
  6.  *                                     R. Brittain  July 4, 1989
  7.  *
  8.  *                This program released to the public domain
  9.  */
  10.  
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <dos.h>
  15.  
  16. extern unsigned char _osmajor;
  17.  
  18. char    *localcopy(char far *);
  19. char     *progname(unsigned int);
  20.  
  21. _setargv() {}
  22. _setenvp() {}
  23.  
  24. main(int argc, char *argv[] )
  25. {
  26.     union REGS regs;
  27.     struct SREGS segregs;
  28.     char far *pfiletab, far *pnext, far *fp;
  29.     char far *name, file[13], far *plist, far *entry;
  30.     char ownername[9], ownerext[5];
  31.     int  nfiles, i, j, numhandles, entrylen;
  32.     unsigned int access, devinfo, progpsp;
  33.     long length, offset;
  34.  
  35.     regs.h.ah = 0x52;                           /* DOS list of lists */
  36.     intdosx(®s,®s,&segregs);
  37.  
  38.     /* make a pointer to start of master list */
  39.     plist    = (char far *)MK_FP(segregs.es,regs.x.bx);
  40.  
  41.     /* pointer to start of file table */
  42.     pfiletab = (char far *)MK_FP(*(int far *)(plist+6), *(int far *)(plist+4));
  43.  
  44.     switch (_osmajor) {
  45.         case 2:
  46.             entrylen = 40;    /* DOS 2.x */
  47.             break;
  48.         case 3:
  49.             entrylen = 53;     /* DOS 3.x */
  50.             break;
  51.         case 4:
  52.             entrylen = 59;  /* DOS 4.x - I do not know what is in the extra 6 bytes */
  53.             break;
  54.         default:
  55.             printf("Sorry, cannot handle this version of MS-DOS");
  56.             exit(1);
  57.     }
  58.  
  59.     printf ("Name          length   offset hnd acc PSP device type/owner\n");
  60.     printf ("----          ------   ------ --- --- --- -----------------\n");
  61.  
  62.     for (;;) {
  63.         /* pointer to next file table */
  64.         pnext    = (char far *)MK_FP(*(int far *)(pfiletab+2), *(int far *)(pfiletab+0));
  65.         nfiles   = *(int far *)(pfiletab+4);
  66. #ifdef DEBUG
  67.         printf ("\nFile table at %Fp entries for %d files\n",pfiletab,nfiles);
  68. #endif
  69.         for (i=0; i<nfiles; i++) {
  70.  
  71.             /* cycle through all files, quit when we reach an unused entry */
  72.             entry = pfiletab + 6 + (i * entrylen);
  73.             if (_osmajor >= 3) {
  74.                 name   = entry + 32 ;
  75.                 strncpy(file, localcopy(name), 11);
  76.                 file[11] = '\0';
  77.                 numhandles = *(int far  *)(entry + 0) ;
  78.                 access     = (int) *(char far *)(entry + 2) ;
  79.                 length     = *(long far *)(entry + 17) ;
  80.                 offset     = *(long far *)(entry + 21) ;
  81.                 devinfo    = *(int far *)(entry + 5) ;
  82.                 progpsp    = *(int far *)(entry + 49);
  83.             } else {
  84.                 name   = entry + 4 ;
  85.                 strncpy(file, localcopy(name), 11);
  86.                 file[11] = '\0';
  87.                 numhandles = (int) *(char far *)(entry + 0) ;
  88.                 access     = (int) *(char far *)(entry + 1) ;
  89.                 length     = *(long far *)(entry + 19) ;
  90.                 offset     = *(long far *)(entry + 36) ;
  91.                 devinfo    = (int) *(char far *)(entry + 27) ;
  92.             }
  93.             if ((strlen(file) > 0) && (numhandles > 0)) {
  94.                 printf("%11.11s %8ld %8ld  %2d ",
  95.                         file,length,offset,numhandles);
  96.                 switch (access) {
  97.                     case 0:
  98.                         printf("r  ");
  99.                         break;
  100.                     case 1:
  101.                         printf("w  ");
  102.                         break;
  103.                     case 2:
  104.                         printf("rw ");
  105.                         break;
  106.                     default:
  107.                         printf("   ");
  108.                 }
  109.                 if (_osmajor >= 3)
  110.                     printf("%04X ",progpsp);
  111.                 else
  112.                     printf("---- ");
  113.  
  114.                 if ((devinfo & 0x80) > 0) {
  115.                     printf("dev: ");
  116.                     if (devinfo & 0x01) printf("stdin ");
  117.                     if (devinfo & 0x02) printf("stdout ");
  118.                     if (devinfo & 0x04) printf("NUL ");
  119.                     if (devinfo & 0x08) printf("CLOCK$ ");
  120.                     if (devinfo & 0x10) printf("fast-tty ");
  121.                     if (devinfo & 0x20) printf("binary ");
  122.                     if (devinfo & 0x1000) printf("network ");
  123.                     printf("\n");
  124.                 } else {
  125.                     printf("drive %c: ",'A'+(devinfo&0x1F));
  126.                     if (devinfo & 0x8000) printf("(network) ");
  127.                     if (_osmajor >= 3) {
  128.                         /* only DOS 3+ can find out the name of the program */
  129.                         fnsplit(progname(progpsp),NULL,NULL,ownername,ownerext);
  130.                         printf("   [%s%s]\n",strlwr(ownername),strlwr(ownerext));
  131.                     } else {
  132.                         printf("\n");
  133.                     }
  134.                 }
  135.             }
  136.             if (strlen(file) == 0) exit(0);
  137.         }
  138.         pfiletab = pnext;
  139.     }
  140. }
  141.  
  142. char *localcopy(char far *s)
  143. /* Make a copy of a string pointed to by a far pointer */
  144. {
  145.     char far *p, *l, *r ;
  146.     int         i=0 ;
  147.     p = s;
  148.     while (*p++ != NULL) { i++; }
  149.     r = l = (char *)malloc(i+1);
  150.     p = s;
  151.     i = 0;
  152.     while (*p != NULL) { *l++ = *p++; i++;}
  153.     *l = '\0';
  154.     return(r);
  155. }
  156.  
  157. char *progname(pid)
  158. unsigned int pid;
  159. /*
  160.  * Return a near pointer to a character string with the full path name
  161.  * of the program whose PSP is given in the argument.  If the argument is
  162.  * invalid, this may return gibberish but I don't know how to tell
  163.  * Offset 0x2C in the PSP in the segment address of the environment of a
  164.  * program.  Beyond the last environment string is a null marker, a word
  165.  * count (usually 1), then the full pathname of the owner of the environment
  166.  * This only works for DOS 3+
  167.  */
  168. {
  169.     unsigned far *envsegptr;    /* Pointer to seg address of environment */
  170.     char far *envptr;            /* Pointer to pid's environment    */
  171.     unsigned far *envsizeptr;    /* Pointer to environment size */
  172.     unsigned envsize;            /* Size of pid's environment */
  173.     unsigned ppid;                /* Parent psp address */
  174.  
  175.     /* find the parent process psp at offset 0x16 of the psp */
  176.     ppid = *(unsigned far *)MK_FP(pid, 0x16);
  177.  
  178.     /* find the environment at offset 2Ch of the psp */
  179.     envsegptr = (unsigned far *) MK_FP (pid,0x2C);
  180.     envptr    = (char far *) MK_FP (*envsegptr,0);
  181.  
  182.     /*
  183.      * Make a pointer that contains the size of the environment
  184.      * block.  Must point back one paragraph (to the environments
  185.      * MCB plus three bytes forward (to the MCB block size field).
  186.      */
  187.     envsizeptr = (unsigned far *) MK_FP(*envsegptr-1,0x3);
  188.     envsize    = *envsizeptr*16;  /* x 16 turns it into bytes */
  189.  
  190.     while (envsize > 0) {
  191.         /* search for end of environment block, or NULL */
  192.         while (--envsize && *envptr++);
  193.  
  194.         /*
  195.          * Now check for another NULL immediately following the first one
  196.          * located and a word count of 0001 following that.
  197.          */
  198.         if (!*envptr && *(unsigned far *) (envptr+1) == 0x1) {
  199.             envptr +=3;
  200.             break;
  201.         }
  202.     }
  203.  
  204.     if (envsize > 0) {
  205.         /* Owner name found - return it */
  206.         return(localcopy(envptr));
  207.     } else {
  208.         if (pid == ppid) {
  209.             /*
  210.              * command.com doesn't leave it's name around, but if pid = ppid
  211.              * then we know we have a shell
  212.              */
  213.             return("-shell-");
  214.         } else {
  215.             return("unknown");
  216.         }
  217.     }
  218. }
  219.